In [1]:
# The tutorial basic_plots.m discussed how to plot data using 'plot' and
# 'errorbar' and then how to format those plots.  In this tutorial we plot
# functions.  Actually, we will give Python a function f(x) and then evaluate
# that function at a bunch of x-values.  You actually have to create a list of x 
# data and then evaluate the function at all those values of x (thus creating 
# a list of y data) and then plot y vs x as in basic_plots.m.  At first, this 
# might seem odd, but it's actually not too bad.  In fact, it gives you full 
# control of the density of points to be used in the plots, whereas other prorams 
# will try to guess for you what might be a good number of points to use.

# I will first import the module numpy and 'matplotlib' which we will use
# for ploting.  Matplotlib provides a MATLAB-like interface.  Many of the 
# options used for plotting in MATLAB are the same in Matplotlib.
import math
import numpy as np
import matplotlib.pyplot as plt
In [2]:
# Here's a simple example of ploting sin x vs x.  First, create some x
# data.
xx = np.array(np.arange(0, 2*math.pi, 0.1))
xx
Out[2]:
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2,
       1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5,
       2.6, 2.7, 2.8, 2.9, 3. , 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8,
       3.9, 4. , 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5. , 5.1,
       5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6. , 6.1, 6.2])
In [4]:
# Next, create the y data
yy = np.sin(xx)
yy
Out[4]:
array([ 0.        ,  0.09983342,  0.19866933,  0.29552021,  0.38941834,
        0.47942554,  0.56464247,  0.64421769,  0.71735609,  0.78332691,
        0.84147098,  0.89120736,  0.93203909,  0.96355819,  0.98544973,
        0.99749499,  0.9995736 ,  0.99166481,  0.97384763,  0.94630009,
        0.90929743,  0.86320937,  0.8084964 ,  0.74570521,  0.67546318,
        0.59847214,  0.51550137,  0.42737988,  0.33498815,  0.23924933,
        0.14112001,  0.04158066, -0.05837414, -0.15774569, -0.2555411 ,
       -0.35078323, -0.44252044, -0.52983614, -0.61185789, -0.68776616,
       -0.7568025 , -0.81827711, -0.87157577, -0.91616594, -0.95160207,
       -0.97753012, -0.993691  , -0.99992326, -0.99616461, -0.98245261,
       -0.95892427, -0.92581468, -0.88345466, -0.83226744, -0.77276449,
       -0.70554033, -0.63126664, -0.55068554, -0.46460218, -0.37387666,
       -0.2794155 , -0.1821625 , -0.0830894 ])
In [5]:
# Finally, create the plot.
plt.plot(xx, yy, 'ro-', markersize = 8, linewidth = 2,  fillstyle = 'none')
plt.xlabel(r'$x$')
plt.ylabel(r'$\sin x$')
plt.axis((0, 2*math.pi, -1, 1));
In [6]:
# Here's another example.  The function plotted below is the frequency
# derivative of a Lorentzian.  We first define a Python function.
def dlorentz(f, f0, Q0):
    return (Q0**2/f)*((f0/f)**2 - (f/f0)**2)/((1 + Q0**2*(f/f0 - f0/f)**2)**(3/2))
In [7]:
# The derivative of the Lorentzian has sharp features near the resonance
# frequency.  First, we show what the plot looks like if we use too few
# points.
f0 = 1e9
Q0 = 500
ff = np.arange(960e6, 1040e6, 2e6)
plt.figure()
plt.plot(ff, dlorentz(ff, f0, Q0), 'bo-', linewidth = 2, fillstyle = 'none')
plt.xlabel('Frequency (Hz)')
plt.ylabel(r'$dL/df$');
In [8]:
# For this second curve we'll use a varying density of points (high density
# near the sharp resonant freatures).  This results in a much smoother
# curve that better represents the true features of the function.
ff = np.concatenate((np.arange(960e6, 990e6, 2e6), np.arange(990e6, 997e6, 1e6),\
  np.arange(997e6, 1003e6, 0.1e6), np.arange(1003e6, 1010e6, 1e6),\
  np.arange(1010e6, 1040e6, 2e6)))
plt.plot(ff, dlorentz(ff, f0, Q0), 'r-', linewidth = 2);